#include "CSceneObject.h"
#include "CLevelEditor.h"
#include "CSetMeshFileCommand.h"
#include "CSetAnimationFileCommand.h"
#include "CSetTextureCommand.h"
#include "IAnimatedObject.h"
#include "CGameObject.h"
#include "IFileSystem.h"
#include "IMeshSceneNode.h"
//#include "CColladaSceneNodeAnimator.h"
#include "Utils\Utils.h"
#include "IrrlichtDevice.h"

extern CLevelEditor* editor;
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
CSceneObject::CSceneObject() : IAnimatedObject() , m_type(E_OBJ_GENERIC)
{	
	m_SceneNode = 0;
	m_UserData = g->device->getFileSystem()->createEmptyAttributes();

	for (int i=0; i < MAX_ROOM_LINKS; i++)
	{
		m_roomIDLinks[i] = -1;
		m_linkIndexLinks[i] = -1;
		m_linkDoorID[i] = -1;
	}
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
CSceneObject::~CSceneObject()
{
	m_UserData->drop();
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
IAttributes* cloneAttributes (IAttributes* attrib)
{
	IAttributes* result = g->device->getFileSystem()->createEmptyAttributes();
	for (u32 i = 0; i < attrib->getAttributeCount(); ++i)
	{
		switch (attrib->getAttributeType(i))
		{
#define ATTRIB_CASE(type, asType) \
	case type: result->setAttribute(attrib->getAttributeName(i), attrib->getAttributeAs ##asType (i)); break

			ATTRIB_CASE(EAT_INT, Int);
			ATTRIB_CASE(EAT_FLOAT, Float);
			ATTRIB_CASE(EAT_BOOL, Bool);
			// special case: ATTRIB_CASE(EAT_ENUM, ???)
			ATTRIB_CASE(EAT_COLOR, Color);
			ATTRIB_CASE(EAT_COLORF, Colorf);
			ATTRIB_CASE(EAT_VECTOR3D, Vector3d);
			ATTRIB_CASE(EAT_POSITION2D, Position2d);
			ATTRIB_CASE(EAT_RECT, Rect);
			ATTRIB_CASE(EAT_MATRIX, Matrix);
			ATTRIB_CASE(EAT_QUATERNION, Quaternion);
			ATTRIB_CASE(EAT_BBOX, Box3d);
			ATTRIB_CASE(EAT_PLANE, Plane3d);
			ATTRIB_CASE(EAT_TRIANGLE3D, Triangle3d);
			ATTRIB_CASE(EAT_LINE2D, Line2d);
			ATTRIB_CASE(EAT_LINE3D, Line3d);
			ATTRIB_CASE(EAT_STRINGWARRAY, Array);

		case EAT_STRING:
			result->setAttribute(attrib->getAttributeName(i), attrib->getAttributeAsStringW(i).c_str());
			break;

		case EAT_ENUM:
		case EAT_FLOATARRAY:
		case EAT_INTARRAY:
		case EAT_BINARY:
		case EAT_TEXTURE:
		case EAT_USER_POINTER:
		default:
			int* a = 0;
			*a = 0;
			break;
#undef ATTRIB_CASE
		}
	}
	return result;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
CSceneObject::CSceneObject (const CSceneObject& object)
{
	m_type = object.m_type;
	//m_Next = object.m_Next;
	m_SceneNode = object.m_SceneNode;
	if (m_SceneNode) m_SceneNode->grab();
	m_UserData = cloneAttributes(object.m_UserData);

	//m_animatorNode = object.m_animatorNode;
	//if (m_animatorNode) m_animatorNode->grab();
	//m_timelineController = object.m_timelineController;
	//if (m_timelineController) m_timelineController->grab();

	for (int i=0; i < MAX_ROOM_LINKS; i++)
	{
		m_roomIDLinks[i] = object.m_roomIDLinks[i];
		m_linkIndexLinks[i] = object.m_linkIndexLinks[i];
		m_linkDoorID[i] = object.m_linkDoorID[i];
	}
}
//--------------------------------------------------------------------------------------------------
// called after create 
//--------------------------------------------------------------------------------------------------
void CSceneObject::InitAttributes( bool create )
{
	if (m_UserData->findAttribute("MeshFile") >=0 )
	{
		CSetMeshFileCommand* command = new CSetMeshFileCommand(m_SceneNode->getID() , m_UserData->getAttributeAsString("MeshFile") , create );
		command->redo();
		command->drop();
	}

	if (m_UserData->findAttribute("AnimationFile") >=0 )
	{
		CSetAnimationFileCommand* command = new CSetAnimationFileCommand(m_SceneNode->getID() , m_UserData->getAttributeAsString("AnimationFile") , create );
		command->redo();
		command->drop();
	}

	if (m_UserData->getAttributeAsString("!GameType") == stringc("SkyBox"))
	{
		CSetTextureCommand* command = new CSetTextureCommand(m_SceneNode->getID() , "TextureFile0" , m_UserData->getAttributeAsString("TextureFile0") );
		command->redo();
		command->drop();
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("Trigger") ||
		m_UserData->getAttributeAsString("!GameType") == stringc("TriggerSound") ||
		m_UserData->getAttributeAsString("!GameType") == stringc("EffectDamage") ||
		m_UserData->getAttributeAsString("!GameType") == stringc("Cover") ||		
		m_UserData->getAttributeAsString("!GameType") == stringc("DropArea") ||
		m_UserData->getAttributeAsString("!GameType") == stringc("TriggerRestore") ||
		m_UserData->getAttributeAsString("!GameType") == stringc("CheckPoint")
		)
	{
		if (m_UserData->findAttribute("Sizes") > -1 )
		{
			editor->updateMeshWithSize( ((IMeshSceneNode*)m_SceneNode)->getMesh() , m_UserData->getAttributeAsVector3d("Sizes") );									
		}
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("CameraDirCtl"))
	{
		if (m_UserData->findAttribute("Size") > -1 && m_UserData->findAttribute("Angle") > -1)
		{
			editor->updateTriPrismMeshWithParams(
					((IMeshSceneNode*)m_SceneNode)->getMesh(), 
					m_UserData->getAttributeAsFloat("Size"),
					m_UserData->getAttributeAsFloat("Angle"));
		}
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("Effect"))
	{
		if (m_UserData->findAttribute("$EffectType") > -1 )
		{			
			editor->SetObjectEffectType(m_SceneNode, m_UserData->getAttributeAsStringW("$EffectType"));
		}
	}
	//@tcy
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("Bonus"))
	{
		if (m_UserData->getAttributeAsBool("SkillPoint") == true)
		{
			m_UserData->setAttribute("WebPower", false) ;
			m_UserData->setAttribute("HP", false) ;
			editor->SetObjectEffectType(m_SceneNode, "bonus_red");
		}
		else if (m_UserData->getAttributeAsBool("WebPower") == true)
		{
			m_UserData->setAttribute("HP", false) ;
			m_UserData->setAttribute("SkillPoint", false) ;
			editor->SetObjectEffectType(m_SceneNode, "bonus_blue");
		}
		else 
		{
			m_UserData->setAttribute("HP", true) ;
			m_UserData->setAttribute("WebPower", false) ;
			m_UserData->setAttribute("SkillPoint", false) ;
			editor->SetObjectEffectType(m_SceneNode, "bonus_green");
		}
		if (m_UserData->findAttribute("$EffectType") > -1 )
			editor->SetObjectEffectType(m_SceneNode, m_UserData->getAttributeAsStringW("$EffectType"));
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("EffectDemage"))
	{
		if (m_UserData->findAttribute("$EffectType") > -1 )
		{			
			editor->SetObjectEffectType(m_SceneNode, m_UserData->getAttributeAsStringW("$EffectType"));
		}
		if (m_UserData->findAttribute("Sizes") > -1 )
		{
			editor->updateMeshWithSize( ((IMeshSceneNode*)m_SceneNode)->getMesh() , m_UserData->getAttributeAsVector3d("Sizes") );									
		}
	}
	else if (m_UserData->getAttributeAsString("!GameType") == "Cinematic")
	{
		stringc sceneFileNameNoExt = editor->m_SceneFileName;
		int idx = editor->m_SceneFileName.findLast('.');
		if (idx != -1)
		{
			sceneFileNameNoExt = editor->m_SceneFileName.subString(0, idx);
		}

		stringc cinematicFile = ".\\cinematics\\";
		cinematicFile += sceneFileNameNoExt;
		cinematicFile += "_";
		cinematicFile += m_SceneNode->getID();
		cinematicFile += "_";
		cinematicFile += "cinematic.cff";
		m_UserData->setAttribute("!ScriptFile", cinematicFile.c_str());
	}
	else if (m_UserData->getAttributeAsString("!GameType") == "ElectricPlatForm")
	{
		//extern void SetMaterialAdditiveByTexName(irr::scene::ISceneNode *Node, const char* texStr);//dai_yx
		//SetMaterialAdditiveByTexName(m_SceneNode, "electric_wr");										
	}

}
//--------------------------------------------------------------------------------------------------
//do mesh stuff here 
//--------------------------------------------------------------------------------------------------
void CSceneObject::ProcessAttributes()
{
	m_SceneNode->setMaterialFlag(EMF_LIGHTING, false);			

	if (m_UserData->findAttribute("MaterialType") >= 0)	
	{
		if (m_SceneNode->getMaterialCount() > 0)
		{
			stringw mStr = m_UserData->getAttributeAsStringW("MaterialType");
			for (int z = 0; z < g->device->getVideoDriver()->getMaterialRendererCount(); z ++)
				if (mStr == g->device->getVideoDriver()->getMaterialRendererName(z))
				{
					m_SceneNode->getMaterial(0).MaterialType = (E_MATERIAL_TYPE)z;
					break;
				}
		}
	}
	
	if (m_UserData->findAttribute("Color") >= 0)
	{
		SColor color;
		color = m_UserData->getAttributeAsColor("Color");
		m_SceneNode->getMaterial(0).EmissiveColor = color;
		
	}
	
	if (m_UserData->findAttribute("Wireframe") >= 0)	
	{
		//m_SceneNode->setMaterialFlag(EMF_WIREFRAME, m_UserData->getAttributeAsBool("Wireframe"));
	}

	if (m_UserData->getAttributeAsString("!GameType") == stringc("WayPoint"))
	{
		m_type = E_OBJ_WAYPOINT;				
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("GridWayPoint"))
	{
		m_type = E_OBJ_GRID_WAYPOINT;				
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("CameraArea"))
	{
		m_type = E_OBJ_CAMERA_AREA;				
	}
	else if (m_UserData->getAttributeAsString("!GameType") == stringc("CamCtrlPoint"))
	{
		m_type = E_OBJ_CAM_CTRL_POINT;				
	}
	else if (m_UserData->getAttributeAsString("!GameType") == "Collisions")
	{
		if ( m_SceneNode->getPosition() != vector3df(0,0,0))
		{		
			m_SceneNode->setPosition(vector3df(0,0,0));
			m_SceneNode->OnAnimate(50.f);
		}		
	}
	else if(m_UserData->getAttributeAsString("!GameType") == stringc("SpiderMan"))
	{
		m_type = E_OBJ_SPIDER_MAN;
	}
	else if(m_UserData->getAttributeAsString("!GameType") == stringc("Cinematic"))
	{
		m_type = E_OBJ_CINEMATIC;
	}


	if (m_UserData->findAttribute("@Anim") >= 0)
	{
		//if (HasAnim())
		//{			
		//	array<stringw> animNames = GetAnimationNames();
		//	int id = animNames.linear_search(m_UserData->getAttributeAsStringW("@Anim"));
		//	id--;
		//	if(id>=0)
		//	{
		//		SetAnim(id);				
		//	}
		//}
	}
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
array<stringw> CSceneObject::GetAnimationNames( bool times )
{
	array<stringw> names;
	names.push_back(L"");

	//if (!m_timelineController) return names;

	//u32 count = m_timelineController->getClipCount();
	//stringw name;
	//for (u32 i=0; i < count; i++)
	//{
	//	name = m_timelineController->getClipName(i);
	//	names.push_back(name);
	//}

	return names;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------

int CSceneObject::GetCurrentAnimationTime( int index )
{
	if (index < 0)
		return -1;

	if (!m_timelineController)
		return -1;

	//f32 time = ceil ( ((f32)m_timelineController->getClipLength(index)) * MAX_ANIM_SAMPLE_FPS / GAME_ANIM_FPS );
	s32 time = 0;//m_timelineController->getClipLength(index);

	return time;
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
